package com.lkx.service.strategy;

import com.lkx.annotation.CloudLimitAnnottion;
import com.lkx.dto.RequestLimitDTO;
import com.lkx.enums.CloudLimitTypeEnum;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.*;

public interface CloudLimitService {

    boolean checkRequestLimit(RequestLimitDTO requestLimitDTO);

    CloudLimitTypeEnum getLimitType();

    default List<RequestLimitDTO> getTokenLimitList(ResourcePatternResolver resourcePatternResolver, CloudLimitTypeEnum cloudLimitTypeEnum,String scanPackage){
        try {
            List<RequestLimitDTO> list = new ArrayList<>();
            Resource[] resources = resourcePatternResolver.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + scanPackage + "/**/*.class");
            MetadataReaderFactory metaReader = new CachingMetadataReaderFactory();
            for (Resource resource : resources) {
                MetadataReader reader = metaReader.getMetadataReader(resource);
                AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();


                Set<MethodMetadata> annotatedMethods = annotationMetadata.getAnnotatedMethods(CloudLimitAnnottion.class.getCanonicalName());
                annotatedMethods.forEach(methodMetadata -> {
                    CloudLimitAnnottion limiter = methodMetadata.getAnnotations().get(CloudLimitAnnottion.class).synthesize();
                    if(!cloudLimitTypeEnum.equals(limiter.type())){
                        return;
                    }
                    RequestLimitDTO dto = new RequestLimitDTO();
                    dto.setKey(methodMetadata.getMethodName());
                    dto.setLimiter(limiter);
                    list.add(dto);
                });
            }
            return list;
        }catch (IOException  e){
            return Collections.emptyList();
        }
    }


}
